package com.rzjm.api.netty.water.handler;

import com.rzjm.api.netty.water.NettyUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.CharsetUtil;
import io.netty.util.ReferenceCountUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class LinkManagementHandler extends ChannelInboundHandlerAdapter {
    private final Logger LOGGER = LoggerFactory.getLogger(LinkManagementHandler.class);

    private static final ByteBuf HEARTBEAT_SEQUENCE =
        Unpooled.unreleasableBuffer(Unpooled.copiedBuffer("HEARTBEAT", CharsetUtil.UTF_8));


    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        String channelId = ctx.channel().id().asLongText();
        int connectionCount = NettyUtil.CONNECTION_COUNT.getAndIncrement();
        LOGGER.info("=======>收到客户端连接 connectionCount={} channelId={}，ctx:{}", connectionCount, channelId, ctx);
        //链接后，主动向设备发送，通知设备连接成功，设备要发送心跳到服务端
        ctx.channel().writeAndFlush("{\"rt\":95,\"v1\":0}");
    }

    /**
     * Channel 离开活动状态并且不再连接它的远程节点时被调用
     * @param ctx
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        String channelId = ctx.channel().id().asLongText();
        String remoteAddress = NettyUtil.getRemoteAddress(ctx);
        int connectionCount = NettyUtil.CONNECTION_COUNT.getAndDecrement();
        LOGGER.error("客户端连接断开,channelInactive connectionCount={} remoteAddress={} channelId={}",
                connectionCount,
                remoteAddress,
                channelId);
        NettyUtil.removeChannel(ctx);
        ctx.close();
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        ReferenceCountUtil.release(msg);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        LOGGER.info("=====>exceptionCaught:{}", cause);
        String channelId = ctx.channel().id().asLongText();
        String remoteAddress = NettyUtil.getRemoteAddress(ctx);
        int connectionCount = NettyUtil.CONNECTION_COUNT.getAndDecrement();
        LOGGER.error("客户端连接断开,exceptionCaught connectionCount={} remoteAddress={} channelId={} cause={}",
                connectionCount,
                remoteAddress,
                channelId,
                cause);
        NettyUtil.removeChannel(ctx);
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {

        if (evt instanceof IdleStateEvent) {

            String socketString = ctx.channel().remoteAddress().toString();

            int connectionCount = NettyUtil.CONNECTION_COUNT.getAndDecrement();

            String channelId = ctx.channel().id().asLongText();
            String remoteAddress = NettyUtil.getRemoteAddress(ctx);

            LOGGER.error("客户端连接断开 connectionCount={} remoteAddress={} channelId={}",
                    connectionCount,
                    remoteAddress,
                    channelId);


            // 发送心跳到远端
//            ctx.writeAndFlush(HEARTBEAT_SEQUENCE.duplicate()).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
            // 关闭连接
            NettyUtil.autoDelChannel(ctx);

            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state() == IdleState.READER_IDLE) {
                LOGGER.info("=======>Client: " + socketString + " READER_IDLE 读超时");
                ctx.close();
                NettyUtil.removeChannel(ctx);
//                NettyUtil.autoDelChannel(ctx);
            } else if (event.state() == IdleState.WRITER_IDLE) {
                LOGGER.info("=======>Client: " + socketString + " WRITER_IDLE 写超时");
                ctx.close();
                NettyUtil.removeChannel(ctx);
//                NettyUtil.autoDelChannel(ctx);
            } else if (event.state() == IdleState.ALL_IDLE) {
                LOGGER.info("=======>Client: " + socketString + " ALL_IDLE 总超时");
                ctx.close();
                NettyUtil.removeChannel(ctx);
//                NettyUtil.autoDelChannel(ctx);
            }
        }
    }
}
